package com.gamutsoft.amb.common.dao;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.hibernate.Session;
import org.hibernate.criterion.Criterion;

import com.gamutsoft.amb.common.bean.CondictionsBean;
import com.gamutsoft.amb.common.bean.QueryExample;
import com.gamutsoft.amb.common.util.PageUtil;
import com.gamutsoft.amb.common.util.QueryUtil;

/**
 * Generic DAO (Data Access Object) with common methods to CRUD POJOs.
 * <p>
 * Extend this interface if you want typesafe (no casting necessary) DAO's for your domain objects.
 * 
 * @author <a href="mailto:bwnoll@gmail.com">Bryan Noll</a>
 * @param <T>
 * a type variable
 * @param <PK>
 * the primary key for that type
 */
public interface IGenericDao<T, PK extends Serializable>
{

	/**
	 * Generic method used to get all objects of a particular type. This is the same as lookup up all rows in a table.
	 * 
	 * @return List of populated objects
	 */
	List<T> getAll();
	
	List<T> findByWhere(T entity, PageUtil pageUtil, Criterion... criterions);
	
	List<T> findByWhereLike(T entity, PageUtil pageUtil, Criterion... criterions);

	/**
	 * Generic method to get an object based on class and identifier. An ObjectRetrievalFailureException Runtime Exception is thrown if nothing is
	 * found.
	 * 
	 * @param id
	 * the identifier (primary key) of the object to get
	 * @return a populated object
	 * @see org.springframework.orm.ObjectRetrievalFailureException
	 */
	T get(PK id);

	/**
	 * Checks for existence of an object of type T using the id arg.
	 * 
	 * @param id
	 * the id of the entity
	 * @return - true if it exists, false if it doesn't
	 */
	boolean exists(PK id);

	/**
	 * Generic method to save an object - handles both update and insert.
	 * 
	 * @param object
	 * the object to save
	 * @return the persisted object
	 */
	T save(T object);

	/**
	 * Generic method to delete an object based on class and id
	 * 
	 * @param id
	 * the identifier (primary key) of the object to remove
	 */
	void remove(PK id);

	/**
	 * Generic method used to get objects by mainTableId. This is the same as lookup up all rows belong to this mainTableId.
	 * 
	 * @return List of populated objects
	 */
	public List<T> retrieveObjectByFK(PK mainTableId, String fk);

	/**
	 * Generic method to delete an object based on mainTableId
	 * 
	 * @param mainTableId
	 * the identifier (foreign key) of the object to remove
	 * @param fk
	 * the foreign key column name
	 */
	public void deleteObjectsByFK(PK mainTableId, String fk);

	/**
	 * get the spring HibernateDaoSupport Session
	 * 
	 * @return Session
	 */
	public Session getSpringHibernateSession();

	/**
	 * release HibernateDaoSupport Session
	 * 
	 * @param session
	 */
	public void releaseHibernateSession(Session session);

	/**
	 * 分页查询 传入sql 、 参数 开始条数和每页显示条数
	 * 
	 * @param sql
	 * @param objs
	 * @param perPageStartNum
	 * @param perPageShowNum
	 * @return list
	 * @author Jay.Wu
	 */
	@SuppressWarnings("unchecked")
	public List findByPage(String sql, Object[] objs, int perPageStartNum, int perPageShowNum);

	/**
	 * 分页查询 传入sql 、 参数 开始条数和每页显示条数
	 * 
	 * @param sql
	 * @param perPageStartNum
	 * @param perPageShowNum
	 * @param order
	 * 无需排序则设置为null
	 * @param objs
	 * @return
	 * @author Jay.Wu
	 */
	@SuppressWarnings("unchecked")
	public List findByPage(String sql, int perPageStartNum, int perPageShowNum, Object... objs);

	/**
	 * 分页查询 传入sql 、 参数(开始页和每页显示条数)
	 * 
	 * @param currPageNum
	 * @param perPageShowNum
	 * @param sql
	 * @param objs
	 * @return
	 * @author bobo.xiang
	 */
	public List<?> findByPage(int currPageNum, int perPageShowNum, String sql, Object... objs);

	/**
	 * 分页查询 传入sql 、 参数(开始页和每页显示条数) community com.loyoyo.common.dao.GenericDao.java
	 * 
	 * @param currPageNum
	 * @param perPageShowNum
	 * @param sql
	 * @param objs
	 * @return List
	 * @author: feifei 2008-8-3 上午11:11:58
	 */
	@SuppressWarnings("unchecked")
	public List findByPageBySql(int currPageNum, int perPageShowNum, String sql, Object... objs);

	/**
	 * 根据属性查找对象.
	 * 
	 * @param propertyName
	 * 属性名
	 * @param value
	 * 属性值
	 * @param order
	 * 排序
	 * @param rowStartIdxAndCount
	 * 可选的分页参数.第一个参数为起始的记录,第二个参数为返回的对象数量. eg. <code>
	 * findByProperty("country","china");      //查找属性值country为china的对象，返回所有对象.
	 * findByProperty("country","china",0,10); //查找属性值country为china的对象，返回第1-10个符合的对象.
	 * </code>
	 * @author Jay.Wu
	 */
	public List<T> findByProperty(final String propertyName, final Object value, String order,
			final int... rowStartIdxAndCount);

	/**
	 * 分页查询 传入SQL 、 参数 开始条数和每页显示条数
	 * 
	 * @param sql
	 * @param perPageStartNum
	 * @param perPageShowNum
	 * @param objs
	 * @return
	 * @author Vincent.luo
	 */
	@SuppressWarnings("unchecked")
	public List findByPageBySql(String sql, int perPageStartNum, int perPageShowNum, Object... objs);

	/**
	 * 根据属性查找对象.
	 * 
	 * @param propertyName
	 * 属性名
	 * @param value
	 * 属性值
	 * @param rowStartIdxAndCount
	 * 可选的分页参数.第一个参数为起始的记录,第二个参数为返回的对象数量. eg. <code>
	 * findByProperty("country","china");      //查找属性值country为china的对象，返回所有对象.
	 * findByProperty("country","china",0,10); //查找属性值country为china的对象，返回第1-10个符合的对象.
	 * </code>
	 * @author Jay.Wu
	 */
	public List<T> findByProperty(final String propertyName, final Object value,
			final int... rowStartIdxAndCount);

	/**
	 * 根据属性查找唯一对象.
	 * 
	 * @return 唯一对象.如果不存在符合条件的结果,返回Null,如果有多个对象符合条件,抛出异常.
	 * @param propertyName
	 * 属性名
	 * @param value
	 * 属性值
	 * @author Jay.Wu
	 */
	public T findUniqueByProperty(final String propertyName, final Object value);

	/**
	 * 直接使用查询语句查询,返回唯一对象
	 * 
	 * @param values
	 * 任意数量的参数.
	 * @return 唯一对象.如果不存在符合条件的结果,返回NULL,如果有多个对象符合条件，抛出异常.
	 * @author Jay.Wu
	 */
	public Object findUnique(final String queryString, final Object... values);

	/**
	 * 利用hibernate Session 普通sql查询方法
	 * 
	 * @param sql
	 * @param values
	 * 任意个数的参数
	 * @return List <HashMap< rs.getMetaData().getColumnName, rs.getObject> >
	 * @throws Exception
	 * @author Jay.Wu
	 */
	@SuppressWarnings("unchecked")
	public List queryMapDataBySql(String sql, Object... values) throws Exception;
	/**
	 * 利用hibernate Session 普通sql查询方法(带分页)
	 * 
	 * @param sql
	 * @param values
	 * 任意个数的参数
	 * @return List <HashMap< rs.getMetaData().getColumnName, rs.getObject> >
	 * @throws Exception
	 * @author Jay.Wu
	 */
	@SuppressWarnings("unchecked")
	public List queryMapDataBySql(String sql , PageUtil pageUtil , Object...values) throws Exception;

	/**
	 * hql查询方法
	 * 
	 * @param hql
	 * @param values
	 * 任意个数的参数
	 * @return
	 * @author Jay.Wu
	 */

	@SuppressWarnings("unchecked")
	public List find(String hql, Object... values);

	/**
	 * 多条件组合查询
	 * 
	 * @param condictions
	 * 需要查询的条件
	 * @param endCondiction
	 * 结束条件
	 * @param fields
	 * 字段
	 * @param conRelation
	 * AND、OR
	 * @param dtoClass
	 * model类
	 * @param rowStartIdxAndCoun
	 * 分页查询
	 * @return
	 * @author Jay.Wu
	 */
	public List<?> findByCondictions(Map<String, Object> condictions, String endCondiction,
			String fields[], String conRelation, String dtoClass, final int... rowStartIdxAndCount);

	/**
	 * 执行更新删除保存
	 * 
	 * @param queryString
	 * @param values
	 * @author Jay.Wu
	 */
	public void executeUpdate(String queryString, Object... values);

	/**
	 * 根据PageUtil设置进行分页查找
	 * 
	 * @param queryString
	 * @param pageUtil
	 * @param objs
	 * @return
	 * @author Jay.Wu
	 */
	@SuppressWarnings("unchecked")
	public List findByPage(String queryString, PageUtil pageUtil, Object... objs);

	/**
	 * 获取表记录总数
	 * 
	 * @param condition
	 * <p>
	 * from后面的条件
	 * <p>
	 * <code>原型："select count(*) from " + condition;</code>
	 * @return
	 * @author Jay.Wu
	 */
	public int countRecordTotal(String condition, Object... values);

	/**
	 * 获取表记录总数
	 * 
	 * @param condition
	 * <p>
	 * from后面的条件
	 * <p>
	 * <code>原型："select count(*) from " + condition;</code>
	 * @return
	 * @author vincent.luo
	 */
	public int countRecordTotalBySql(String condition, Object... values);

	/**
	 * 通过普通SQL 更新数据库数据
	 *  
	 * @param queryString
	 * @param values
	 * @throws Exception
	 */
	public void updateBySql(String queryString, Object... values) throws Exception;

	/**
	 * 根据PageUtil设置进行分页查找
	 * 
	 * @param queryString
	 * @param pageUtil
	 * @param objs
	 * @return
	 * @author Vincent.luo
	 */
	@SuppressWarnings("unchecked")
	public List findByPageBySql(String queryString, PageUtil pageUtil, Object... objs);

	/**
	 * 排序查找此类型的所有对象
	 * 
	 * @param order
	 * @return
	 * @author Jay.Wu
	 */
	public List<T> getAll(String order);

	/**
	 * 组合条件查找
	 * 
	 * @param condictions
	 * @param endCondiction
	 * @param fields
	 * @param conRelation
	 * @param dtoClass
	 * @param rowStartIdxAndCount
	 * @return
	 * @author Jay.Wu
	 */
	@SuppressWarnings("unchecked")
	public List findByCondictions(List<CondictionsBean> condictions,
			String[] fields, String endCondiction, String conRelation,
			String dtoClass, int[] rowStartIdxAndCount);
	
	/**
	 * 根据查询条件查询（暂时只支持SQL）
	 * 
	 * @author Vincent.luo
	 * @param sql
	 * @param queryExample
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<Map> findByQueryExample(String sql , QueryExample queryExample);

	/**
	 * 插入一条新记录
	 * 
	 * @param entity
	 */
	public void create(T entity);

	/**
	 * 多条件查询
	 * 
	 * @param queryUtil
	 * @return
	 */
	public List findByCondictions(QueryUtil queryUtil);
	public String generateNoSeq() throws Exception;
}
